package nl.saxion.ein4b.controller;

import nl.saxion.ein4b.model.Card;
import nl.saxion.ein4b.model.CardStack;
import nl.saxion.ein4b.model.Player;
import nl.saxion.ein4b.model.Profile;
import nl.saxion.ein4b.model.RealPlayer;

public class Blackjack {

	RealPlayer player;
	private CardStack mainCardStack;
	private CardStack playerStack = new CardStack();
	private CardStack dealerStack = new CardStack();

	private CardStack extraStack;
	private boolean won;
	private boolean lost;
	private boolean split;

	public Blackjack(Profile profile) {
		player = new RealPlayer(profile);
	}

	public void setup() {
		// deal cards
		mainCardStack = new CardStack();
		dealerStack = new CardStack();

		// shuffle cards
		mainCardStack.createCardStack();

		playerStack = player.getStack();

		// deal 2 cards to player
		playerStack.push(mainCardStack.pop());
		playerStack.push(mainCardStack.pop());
		// deal 1 cards to dealer
		dealerStack.push(mainCardStack.pop());
		// dealerStack.push(mainCardStack.pop());

		if ((getPlayerHandValue() == 21 || getDealerHandValue() == 21)) {
			stand();
		}
	}

	public boolean canDeal() {
		boolean result = false;
		if (player.getBetValue() == 0)
			return false;
		if (mainCardStack == null) {
			result = true;
		}
		return result;
	}

	// bet///////////////////////////////////
	public void bet(int amount) {
		if (canBet(amount)) {
			player.setCredit(player.getCredit() - amount);
			player.setBetValue(amount);
		}
	}

	public boolean canBet(int amount) {
		boolean result = false;
		if (playerStack.getCardStack().isEmpty()) {
			if (amount <= player.getCredit()
					&& (player.getBetValue() + amount) <= 1000) {
				result = true;
			}
		}
		return result;
	}

	// ///////////////////////////////////////////

	// hit///////////////////////////////////////
	public void hit(CardStack stack) {
		stack.push(mainCardStack.pop());
		if (getPlayerHandValue() == 21)
			stand();
		check(stack);
	}

	public boolean canHit() {
		boolean result = false;
		if (!playerStack.getCardStack().isEmpty()) {
			if (getPlayerHandValue() < 21) {
				result = true;
			}
		}
		return result;
	}

	// /////////////////////////////////////////

	// stand///////////////////////////////////////////////////
	public void stand() {
		//
		if (!(getPlayerStack().getCardStack().size() == 2 && getPlayerHandValue() == 21)) {
			while (getDealerHandValue() < 17) {
				dealerStack.push(mainCardStack.pop());
			}
		}

		// if dealer wins
		if (getDealerHandValue() > getPlayerHandValue()
				&& getDealerHandValue() <= 21) {
			lost = true;
			// if blackjack
		} else if (getPlayerHandValue() == 21 && getDealerHandValue() < 21
				&& playerStack.getCardStack().size() == 2) {
			player.setCredit(player.getCredit() + 3 * player.getBetValue());
			won = true;
			// if you win
		} else if (((getPlayerHandValue() > getDealerHandValue()) && getPlayerHandValue() <= 21)
				|| (getPlayerHandValue() <= 21 && getDealerHandValue() > 21)) {
			player.setCredit(player.getCredit() + 2 * player.getBetValue());
			won = true;
		}
		// if push
		else if (getPlayerHandValue() == getDealerHandValue()) {
			player.setCredit(player.getCredit() + player.getBetValue());
			won = true;
		}

	}

	public boolean canStand() {
		boolean result = false;
		if (playerStack != null) {
			if (playerStack.getCardStack().size() > 0) {
				result = true;
			}
		}
		return result;
	}

	// /////////////////////////////////////

	// check////////////////////////////////////////////////
	public void check(CardStack stack) {
		int totalValue = 0;
		for (Card c : stack.getCardStack()) {
			totalValue += c.getcardType().getValue();
		}
		if (totalValue > 21 && !playerStack.isSplit()) {
			System.out.println("einde spel verloren :(((");
			lost = true;
		}
	}

	// ////////////////////////////////////////////////////

	// doubledown//////////////////////////////////////
	public void doubleDown() {

		if (canDoubleDown()) {

			// haal zelfde betvalue er nog eens af
			player.setCredit(player.getCredit() - player.getBetValue());
			// set betvalue naar 2x betvalue
			player.setBetValue(2 * player.getBetValue());
			hit(player.getStack());
			stand();
		}
	}

	public boolean canDoubleDown() {
		boolean result = false;
		if (playerStack != null) {
			if (player.getBetValue() <= player.getCredit()
					&& (getPlayerHandValue() == 9 || getPlayerHandValue() == 10 || getPlayerHandValue() == 11)) {
				result = true;
			}
		}
		return result;
	}

	// ////////////////////////////////////////////////

	// split//////////////////////////////////
	public void insure() {
		player.setInsured();
	}

	public CardStack getExtraStack() {
		return extraStack;
	}

	public boolean canSplit() {

		return false;

	}

	// ////////////////////////////////////////////////

	// get and set
	public int getPlayerHandValue() {
		int totalValue = 0;
		int aces = 0;
		for (Card c : playerStack.getCardStack()) {
			totalValue += c.getcardType().getValue();
			if (c.getcardType().getValue() == 1) {
				aces++;
			}
		}
		if (totalValue <= 11) {
			if (aces > 0) {
				totalValue += 10;
				aces--;
			}
		}
		return totalValue;
	}

	public int getDealerHandValue() {
		int totalValue = 0;
		int aces = 0;
		for (Card c : dealerStack.getCardStack()) {
			totalValue += c.getcardType().getValue();
			if (c.getcardType().getValue() == 1) {
				aces++;
			}
		}
		if (totalValue <= 11) {
			if (aces > 0) {
				totalValue += 10;
				aces--;
			}
		}
		return totalValue;
	}

	public CardStack getDealerStack() {
		return dealerStack;
	}

	public boolean hasWon() {
		return won;
	}

	public boolean hasLost() {
		return lost;
	}

	public CardStack getPlayerStack() {
		return playerStack;
	}

	public Player getPlayer() {
		return player;
	}

	public CardStack getMainStack() {
		return mainCardStack;
	}

	public Profile getProfile() {
		return player.getProfile();
	}

	public boolean canRefill() {
		return (player.getProfile().getCredit() == 0)
				&& (player.getBetValue() == 0);
	}

	public void refill() {
		player.getProfile().setCredit(100);
	}

}